#version 410 core


struct Material
{
	// 漫反射贴图
	sampler2D   diffuse;

	// 反光度
	// 越大  亮点越小 光束越集中
	float shininess;
};

out vec4 FragColor;

uniform vec3 viewPos;
uniform Material material;
uniform sampler2D shadowMap;
uniform vec3 lightPos;

in VS_OUT {
	vec3 Normal;
	vec3 FragPos;
	vec2 TexCoords;
	vec4 FragPosLightSpace;
} fs_in;


vec3 calcDirLight(Material material, vec3 normal, vec3 viewDir, vec2 texCoords);


float ShadowCalculation(vec3 normal, vec3 lightDir, vec4 fragPosLightSpace)
{
    // perform perspective divide
    vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
    // transform to [0,1] range
    projCoords = projCoords * 0.5 + 0.5;

    if(projCoords.z > 1.0)
        return 0;

    float shadow = 0.0;
    vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
    for(int x = -1; x <= 1; ++x)
    {
        for(int y = -1; y <= 1; ++y)
        {
            float currentDepth = projCoords.z;
            float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
            float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
            shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
        }
    }
    shadow /= 9.0;
    // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
    //float closestDepth = texture(shadowMap, projCoords.xy).r;
    // get depth of current fragment from light's perspective
   // float currentDepth = projCoords.z;
    // check whether current frag pos is in shadow

   // float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);

    //float shadow = currentDepth - bias> closestDepth  ? 1.0 : 0.0;
    //float shadow = currentDepth > closestDepth  ? 1.0 : 0.0;

    return shadow;
}


void main()
{
    vec3 lightColor = vec3(0.7);

	vec3 normal = normalize(fs_in.Normal);

	vec3 viewDir = normalize(viewPos - fs_in.FragPos);

	vec3 lightDir = normalize(lightPos - fs_in.FragPos);
	// 漫反射着色
	float diff = max(dot(normal, lightDir), 0.0);
	// 镜面光着色
	vec3 reflectDir = reflect(-lightDir, normal);
	float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);

    vec3 color = texture(material.diffuse, fs_in.TexCoords).rgb;

    vec3 ambient = 0.3 * lightColor;
	vec3 diffuse  = diff * lightColor;
	vec3 specular =  spec * lightColor;

    float shadow = ShadowCalculation(normal, lightDir, fs_in.FragPosLightSpace);
    vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color;
	FragColor = vec4(lighting, 1.0);
}
